'''
实验名称：MQTT通信
版本：v1.1
日期：2021.8
作者：01Studio
说明：编程实现MQTT通信，实现发布数据。
MQTT助手：http://www.tongxinmao.com/txm/webmqtt.php#collapseOne
'''
import network,dht,time
from simple import MQTTClient #导入MQTT板块
from machine import I2C,Pin,Timer,ADC
from ssd1306 import SSD1306_I2C
import onewire,ds18x20

import json

SERVER = '175.178.132.26'
PORT = 9501
CLIENT_ID = '01Studio-ESP832' # 客户端ID
TOPIC = 'esp32' # TOPIC名称

#初始化相关模块
i2c = I2C(sda=Pin(13), scl=Pin(14))
oled = SSD1306_I2C(128, 64, i2c, addr=0x3c)

adc = ADC(Pin(36))

#初始化DS18B20
ow= onewire.OneWire(Pin(4)) #使能单总线
ds = ds18x20.DS18X20(ow)        #传感器是DS18B20
rom = ds.scan()         #扫描单总线上的传感器地址，支持多个传感器同时连接

#创建DTH11对象
d = dht.DHT11(Pin(27)) #传感器连接到引脚15
time.sleep(1)   #首次启动停顿1秒让传感器稳定

#WIFI连接函数
def WIFI_Connect():

    WIFI_LED=Pin(2, Pin.OUT) #初始化WIFI指示灯

    wlan = network.WLAN(network.STA_IF) #STA模式
    wlan.active(True)                   #激活接口
    start_time=time.time()              #记录时间做超时判断

    if not wlan.isconnected():
        print('connecting to network...')
        wlan.connect('CMCC-xcXx', 'at3LyXeE') #输入WIFI账号密码

        while not wlan.isconnected():

            #LED闪烁提示
            WIFI_LED.value(1)
            time.sleep_ms(300)
            WIFI_LED.value(0)
            time.sleep_ms(300)

            #超时判断,15秒没连接成功判定为超时
            if time.time()-start_time > 15 :
                print('WIFI Connected Timeout!')
                break

    if wlan.isconnected():
        #LED点亮
        WIFI_LED.value(1)

        #串口打印信息
        print('network information:', wlan.ifconfig())

        #OLED数据显示（如果没接OLED，请将下面代码屏蔽）
        oled.fill(0)   #清屏背景黑色
        oled.text('IP/Subnet/GW:',0,0)
        oled.text(wlan.ifconfig()[0], 0, 20)
        oled.text(wlan.ifconfig()[1],0,38)
        oled.text(wlan.ifconfig()[2],0,56)
        oled.show()
        return True

    else:
        return False

#接收数据任务
def MQTT_Rev(tim):
    client.check_msg()

def temp_get(timDs):
    ds.convert_temp()
    temp = ds.read_temp(rom[0]) #温度显示,rom[0]为第1个DS18B20
    result = str('%.2f'%temp)+' C'
    respon = {"d":"temp","p":0,"s":result}
    client.publish('web', json.dumps(respon))


def dht_get(timDht):
    d.measure()         #温湿度采集
    result = str(d.temperature() )+' C'+'/'+str(d.humidity())+' %'
    respon = {"d":"dht","p":0,"s":result}
    client.publish('web', json.dumps(respon))

#led 控制函数
def gpioLed(msg):
    #引脚编号
    pinNum = int(msg['p'])
    #引脚电平1或0
    state = int(msg['s'])
    LED=Pin(pinNum, Pin.OUT)
    nowState = LED.value()
    LED.value(state)
    print("led on")
    respon = {"d":"led","p":pinNum,"s":LED.value()}
    return json.dumps(respon)

def oledMsgShow(msg):
    oled.fill(0)   #清屏背景黑色
    oled.text('mqttMsg:',0,0)
    oled.text(msg['info'], 0, 20)
    oled.show()
    return ''

def ADC_Test(msg):
    result = str('%.2f'%(adc.read()/4095))
    respon = {"d":"adc","p":0,"s":result}
    return json.dumps(respon)


#业务控制函数
controller = {"led":gpioLed,"oled":oledMsgShow,"adc":ADC_Test}

#设置MQTT回调函数,有信息时候执行
def MQTT_callback(topic, msg):
    #print('topic: {}'.format(topic))
    #print('msg: {}'.format(msg))
    #oled.fill(0)   #清屏背景黑色
    #oled.text('{}'.format(msg), 0, 56)
    #oled.show()
    resp = json.loads(msg.decode())
    if 'd' not in resp:
        print("device not found")
    else:
        device = resp['d']
        if device in controller:
            result = controller[device](resp)
            if (result):
                client.publish('web', result)


#执行WIFI连接函数并判断是否已经连接成功
if WIFI_Connect():
    client = MQTTClient(CLIENT_ID, SERVER, PORT)
    client.set_callback(MQTT_callback)
    client.connect()
    client.subscribe(TOPIC) #订阅主题


    #开启RTOS定时器，编号为-1,周期1000ms，执行socket通信接收任务
    tim = Timer(-1)
    timDs = Timer(-2)
    timDht = Timer(-3)
    tim.init(period=300, mode=Timer.PERIODIC,callback=MQTT_Rev)
    timDs.init(period=5000, mode=Timer.PERIODIC,callback=temp_get)
    timDht.init(period=5000, mode=Timer.PERIODIC,callback=dht_get)




